home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Utilities / Unix / satan-1.1.1 / perl / targets.pl < prev    next >
Text File  |  1995-04-10  |  8KB  |  360 lines

  1. #
  2. # get_proximity(target) returns proximity by hostname.
  3. #
  4. # new_target(target, proximity) figures out what (still) needs to be done.
  5. #
  6. # save_all_hosts(path) saves the all_hosts table to file.
  7. #
  8. # read_all_hosts(path) reads the all_hosts table from file.
  9. #
  10. # drop_all_hosts(host) forget this host.
  11. #
  12. # merge_all_hosts(path) merge with in-core tables.
  13. #
  14. # set_host_time(host) set host access time (UTC).
  15. #
  16. # get_host_time(host) get host access time (UTC).
  17. #
  18. # version 3, Mon Mar 20 19:43:59 1995, last mod by wietse
  19. #
  20.  
  21. require 'perl/policy-engine.pl';
  22. require 'perl/subnets.pl';
  23. require 'perl/domains.pl';
  24. require 'perl/get_host.pl';
  25. require 'perl/shell.pl';
  26.  
  27. #
  28. # Get proximity for this host.
  29. #
  30. sub get_proximity
  31. {
  32.     local($target) = @_;
  33.  
  34.     return 100 unless defined($all_hosts{$target});
  35.     return $all_hosts{$target}{'proximity'};
  36. }
  37.  
  38. #
  39. # Set up a list of primary targets. Primaries are special. They may be
  40. # expanded. After all the primaries are known we may have to do something
  41. # special, like forgetting everything we know about them.
  42. #
  43. sub add_primary_target {
  44.     local($target) = @_;
  45.  
  46.     # Do we expand or do we scan a host.
  47.     if ($target =~ /^\d+\.\d+\.\d+$/ || $attack_proximate_subnets) {
  48.         print "Add-primary: expand $target...\n" if $debug;
  49.         &target_acquisition($target, 0, $attack_level);
  50.     } else {
  51.         print "Add-primary: $target\n" if $debug;
  52.         &new_target($target, 0);
  53.     }
  54. }
  55.  
  56. #
  57. # Forget everything we know about primary targets (well, almost everything).
  58. # We must re-read the data base, or memory would be polluted with stale
  59. # inferences.
  60. #
  61. sub fix_primary_targets {
  62.     local(%temp_targets);
  63.  
  64.     if ($primaries_deleted) {
  65.         print "Primaries being rescanned, rebuilding tables.\n" if $debug;
  66.         %temp_targets = %new_targets;
  67.         &save_satan_data();
  68.         &read_satan_data();
  69.         %new_targets = %temp_targets;
  70.         $primaries_deleted = 0;
  71.     }
  72. }
  73.  
  74. #
  75. # Take a new potential target and let it cool down. This saves lots of
  76. # duplicate work.
  77. #
  78. sub new_target
  79. {
  80.     local($target, $proximity) = @_;
  81.  
  82.     return unless $target;
  83.  
  84.     # Make sure all current primaries are rescanned, not the hosts that
  85.     # were primaries during some earlier scan.
  86.     if ($proximity == 0) {
  87.         $primaries_deleted = defined($all_hosts{$target});
  88.         drop_old_todos($target);
  89.         drop_old_facts($target);
  90.     }
  91.  
  92.     # Toss circular paths.
  93.     if (defined($all_hosts{$target})
  94.         && $all_hosts{$target}{'proximity'} < $proximity) {
  95.         return;
  96.     }
  97.     if (exists($new_targets{$target}) 
  98.         && $new_targets{$target} <= $proximity) {
  99.         return;
  100.     }
  101.  
  102.     # Keep primary, keep shortest path.
  103.     if ($proximity == 0 || !exists($new_targets{$target}) 
  104.         || !defined($all_hosts{$target}) 
  105.         || $all_hosts{$target}{'proximity'} > $proximity) {
  106.         $new_targets{$target} = $proximity;
  107.         print "Add-target: $target prox $proximity\n" if $debug;
  108.     }
  109. }
  110.  
  111. #
  112. # Probe targets.
  113. #
  114. sub process_targets
  115. {
  116. local($target, $proximity, $level, %temp_targets, %probe_targets);
  117.  
  118. while(sizeof(*new_targets) > 0) {
  119.     %temp_targets = %new_targets;
  120.     %new_targets = ();
  121.     %probe_targets = ();
  122.  
  123.     # Generate probes according to policy restrictions.
  124.     for $target (keys %temp_targets) {
  125.         $proximity = $temp_targets{$target};
  126.  
  127.         # Instantiate new host.
  128.         if (!defined($all_hosts{$target})) {
  129.             &add_new_host($target, $proximity);
  130.             }
  131.  
  132.         # Proximity may have changed.
  133.         if ($all_hosts{$target}{'proximity'} > $proximity) {
  134.             $all_hosts{$target}{'proximity'} = $proximity;
  135.             }
  136.  
  137.         # Skip attack and target expansion if this host is off-limits.
  138.         if (($level = &policy_engine($target, $proximity)) < 0) {
  139.             print "process_targets: skip $target...\n" if $debug;
  140.             next;
  141.             }
  142.  
  143.         # Attack level contents may have changed.
  144.         $all_hosts{$target}{'attack'} = $level;
  145.         $check_alive_list .= "$target "
  146.             if !defined($host_is_alive{$target});
  147.         $probe_targets{$target} = $level;
  148.         }
  149.     }
  150.  
  151.     # Parallelize liveness checks.
  152.     &check_alive();
  153.  
  154.     # Generate the probes.
  155.     for $target (keys %probe_targets) {
  156.         print "process_targets: probe $target...\n" if $debug;
  157.         &target_attack($target, $probe_targets{$target});
  158.     }
  159. }
  160.  
  161. #
  162. # Add one target to the %all_hosts list. Set proximity, IP, preliminary
  163. # attack level, preliminary expansion flag.
  164. #
  165. sub add_new_host
  166. {
  167. local($target, $proximity) = @_;
  168.  
  169. $all_hosts{$target}{'proximity'} = $proximity;
  170. $all_hosts{$target}{'attack'} = -1;
  171. $all_hosts{$target}{'expand'} = 0;
  172. $all_hosts{$target}{'IP'} = &get_host_addr($target);
  173. $subnet_flag = 0;
  174. $domain_flag = 0;
  175. }
  176.  
  177. #
  178. # ping a list of hosts and find out what hosts are alive.
  179. #
  180. sub check_alive {
  181.     local ($host);
  182.  
  183.     if ($check_alive_list eq "") {
  184.         return;
  185.     }
  186.     print "Check-pulse: $check_alive_list\n" if $debug;
  187.  
  188.     #
  189.     # Cheat when ICMP is broken.
  190.     #
  191.     if ($dont_use_ping) {
  192.         for $host (split(/\s+/, $check_alive_list)) {
  193.             $host_is_alive{$host} = 1;
  194.             $live_hosts++;
  195.         }
  196.         $check_alive_list = "";
  197.         return;
  198.     }
  199.  
  200.     #
  201.     # Fping or bust.
  202.     #
  203.     &open_cmd(FPING, $long_timeout, "$FPING $check_alive_list") 
  204.         || die "cannot run $FPING: $!\n";
  205.     while(<FPING>) {
  206.         if (/(\S+) is alive/) {
  207.             $host_is_alive{$1} = 1;
  208.             $live_hosts++;
  209.         } elsif ($debug && /(\S+) is unreachable/) {
  210.             print "Skipping dead host - $1\n";
  211.         }
  212.     }
  213.     close(FPING);
  214.     $check_alive_list = "";
  215. }
  216.  
  217. #
  218. # target attack; assign attacks, throw into todo queue
  219. #
  220. sub target_attack
  221. {
  222. local($target, $level) = @_;
  223.  
  224. if ($host_is_alive{$target}) {
  225.     print "Prox: $all_hosts{$target}{'proximity'}\n" if $debug;
  226.     print "AL  : $all_hosts{$target}{'attack'}\n" if $debug;
  227.     print "ALC : $all_hosts{$parent}{'attack'}\n" if $parent && $debug;
  228.  
  229.     for (@{$all_attacks[$level]}) {
  230.         &add_todo($target, $_, "") if ! /\?/;
  231.         }
  232.     }
  233. }
  234.  
  235. #
  236. # target acq; get subnets
  237. #
  238. sub target_acquisition
  239. {
  240. local($target, $proximity, $level) = @_;
  241. local($targets_found);
  242.  
  243. # Expand and then collect. Pass results through new_target() for
  244. # consistent handling of constraints and policies.
  245. &open_cmd (TARGETS, 120, "$GET_TARGETS $target");
  246. while (<TARGETS>) {
  247.     chop;
  248.     next unless $_ = getfqdn($_);
  249.     if (!defined($all_hosts{$_})) {
  250.         &add_new_host($_, $proximity);
  251.         }
  252.     $all_hosts{$_}{'proximity'} = $proximity 
  253.         if ($all_hosts{$_}{'proximity'} > $proximity);
  254.     $all_hosts{$_}{'expand'} = 1;
  255.     $host_is_alive{$_} = 1;
  256.     $live_hosts++;
  257.     &new_target($_, $proximity);
  258.     $targets_found++;
  259.     }
  260. close(TARGETS);
  261. die "$GET_TARGETS failed - unable to expand subnet $target\n" 
  262.     if ($? || $targets_found < 1)
  263. }
  264.  
  265. #
  266. # Save the %all_hosts array
  267. #
  268. sub save_all_hosts {
  269. local($all_hosts_file) = @_;
  270. local($record, $host, $ip, $proximity, $level, $expand, $time);
  271.  
  272. open(ALL_HOSTS, ">$all_hosts_file") ||
  273.     die "Can't open $all_hosts_file (cache for all-hosts) for writing\n";
  274.  
  275. for $host (keys %all_hosts) {
  276.     $ip = $all_hosts{$host}{'IP'};
  277.     $proximity = $all_hosts{$host}{'proximity'};
  278.     $level = $all_hosts{$host}{'attack'};
  279.     $expand = $all_hosts{$host}{'expand'};
  280.     $time = $all_hosts{$host}{'time'};
  281.     $record = "$host|$ip|$proximity|$level|$expand|$time";
  282.     print ALL_HOSTS "$record\n";
  283.     # print "save_all_hosts: $record\n" if $debug;
  284.     }
  285. close(ALL_HOSTS);
  286.  
  287. }
  288.  
  289. #
  290. # Reset host info and derivatives
  291. #
  292. sub clear_all_hosts {
  293.     %all_hosts = ();
  294.     %new_targets = ();
  295.     &clear_subnet_info();
  296.     &clear_domain_info();
  297. }
  298.  
  299. #
  300. # suck in the all-hosts array from file
  301. #
  302. sub read_all_hosts {
  303.     local($all_hosts_file) = @_;
  304.  
  305.     &clear_all_hosts();
  306.     &merge_all_hosts($all_hosts_file);
  307. }
  308.  
  309. #
  310. # merge the in-core all-hosts array with one from file
  311. #
  312. sub merge_all_hosts {
  313. local($all_hosts_file) = @_;
  314. local($count, $host, $ip, $proximity, $level, $time);
  315.  
  316. open(ALL_HOSTS, $all_hosts_file) ||
  317.     die "Can't open $all_hosts_file (cache for all-hosts) for reading\n";
  318.     print "Reading all hosts info from $all_hosts_file...\n" if $debug;
  319.  
  320. # read one line at a time, herky jerky motion... one trick pony, man...
  321. while (<ALL_HOSTS>) {
  322.     chop;
  323.     $count = ($host, $ip, $proximity, $level, $expand, $time) = split(/\|/);
  324.     if ($count != 6) {
  325.         warn "corrupted $all_hosts_file: $_\n";
  326.         next;
  327.         }
  328.     if (!defined($all_hosts{$host}{'proximity'})
  329.         || $all_hosts{$host}{'proximity'} > $proximity) {
  330.         $all_hosts{$host}{'IP'} = $ip;
  331.         $all_hosts{$host}{'proximity'} = $proximity;
  332.         $all_hosts{$host}{'attack'} = $level;
  333.         $all_hosts{$host}{'expand'} = $expand;
  334.         $all_hosts{$host}{'time'} = $time;
  335.         }
  336.     }
  337. close(ALL_HOSTS);
  338. }
  339.  
  340. #
  341. # set the last access time for this host. Use numerical form for easy sorting.
  342. #
  343. sub set_host_time {
  344.     local($host) = @_;
  345.  
  346.     $all_hosts{$host}{'time'} = time();
  347. }
  348.  
  349. #
  350. # get the last access time for this host. Use numerical form for easy sorting.
  351. #
  352. sub get_host_time {
  353.     local($host) = @_;
  354.  
  355.     return $all_hosts{$host}{'time'};
  356. }
  357.  
  358.  
  359. 1;
  360.